home *** CD-ROM | disk | FTP | other *** search
/ Hobby PC 15 / Hobby PC 15.iso / Soft / Blender / blender.exe / ic255.cab / python / lwo2iv.py < prev    next >
Text File  |  2001-03-15  |  15KB  |  388 lines

  1. #! /usr/bin/env python
  2.  
  3. #######################
  4. # (c) Jan Walter 2000 #
  5. #######################
  6.  
  7. # CVS
  8. # $Author: jan $
  9. # $Date: 2000/12/14 15:34:25 $
  10. # $RCSfile: lwo2iv.py,v $
  11. # $Revision: 1.1 $
  12.  
  13. # why not use the chunk module ???
  14.  
  15. import sys
  16. import string
  17. import struct
  18. import os
  19.  
  20. def usage():
  21.     print 'usage: python lwo2iv.py "filename.lwo"'
  22.  
  23. def readChunk(file):
  24.     tag = file.read(4)
  25.     data = struct.unpack(">L", file.read(4)) # big endian
  26.     length = data[0]
  27.     return tag, length
  28.  
  29. def readFace(file):
  30.     bytes = 0
  31.     numvert = struct.unpack(">H", file.read(2)) # numvert
  32.     bytes = bytes + 2
  33.     numvert = numvert[0]
  34.     verts = []
  35.     for index in xrange(numvert):
  36.         vert = struct.unpack(">H", file.read(2)) # vert
  37.         bytes = bytes + 2
  38.         verts.append(vert[0])
  39.     surf = struct.unpack(">h", file.read(2)) # surf
  40.     bytes = bytes + 2
  41.     surf = surf[0]
  42.     face = numvert, verts, surf
  43.     return face, bytes
  44.  
  45. def readFaceList(file, length):
  46.     faceList = []
  47.     numFaces = 0
  48.     bytes = 0
  49.     while bytes < length:
  50.         face, numBytes = readFace(file)
  51.         bytes = bytes + numBytes
  52.         faceList.append(face)
  53.     print "numFaces:", len(faceList)
  54.     return faceList
  55.  
  56. def readPoint(file):
  57.     return struct.unpack(">3f", file.read(12)) # big endian
  58.  
  59. def readPointList(file, length):
  60.     pointList = []
  61.     numPoints = length / 12
  62.     print "numPoints:", numPoints
  63.     for index in xrange(numPoints):
  64.         point = readPoint(file)
  65.         pointList.append(point)
  66.     return pointList
  67.  
  68. def readSurfaceDefinition(file, length):
  69.     surfaceDefinition = []
  70.     bytes = file.read(length)
  71.     words = string.split(bytes, '\0')
  72.     bytes = bytes[(len(words[0])+1):]
  73.     # skip \0
  74.     while bytes[0] == '\0':
  75.         bytes = bytes[1:]
  76.     while bytes != '':
  77.         subChunk, bytes = readSurfaceSubChunk(bytes)
  78.         surfaceDefinition.append(subChunk)
  79.     return surfaceDefinition
  80.  
  81. def readSurfaceSubChunk(bytes):
  82.     subChunk = []
  83.     tag = bytes[:4]
  84.     bytes = bytes[4:]
  85.     data = struct.unpack(">H", bytes[:2])
  86.     bytes = bytes[2:]
  87.     length = data[0]
  88.     if tag in ["COLR", "TCLR"]:
  89.         subChunk.append(tag)
  90.         r, g, b, pad = struct.unpack(">4B", bytes[:4])
  91.         bytes = bytes[4:]
  92.         subChunk.append((r, g, b))
  93.     elif tag in ["FLAG", "RFLT", "TFLG", "TFRQ"]:
  94.         subChunk.append(tag)
  95.         value = struct.unpack(">H", bytes[:2])
  96.         value = value[0]
  97.         bytes = bytes[2:]
  98.         subChunk.append(value)
  99.     elif (tag in ["LUMI", "DIFF", "SPEC", "REFL", "TRAN", "GLOS", "TVAL"] or
  100.           tag[:3] == "TIP"):
  101.         subChunk.append(tag)
  102.         value = struct.unpack(">h", bytes[:2])
  103.         value = value[0]
  104.         bytes = bytes[2:]
  105.         subChunk.append(value)
  106.     elif (tag in ["VLUM", "VDIF", "VSPC", "VRFL", "VTRN", "RSAN", "RIND",
  107.                   "EDGE", "SMAN", "TAMP", "TAAS", "TOPC"] or
  108.           tag[:3] == "TFP" or tag[:3] == "TSP"):
  109.         subChunk.append(tag)
  110.         value = struct.unpack(">f", bytes[:4])
  111.         value = value[0]
  112.         bytes = bytes[4:]
  113.         subChunk.append(value)
  114.     elif tag in ["RIMG", "CTEX", "DTEX", "STEX", "RTEX", "TTEX", "LTEX",
  115.                  "BTEX", "TIMG", "TALP"]:
  116.         subChunk.append(tag)
  117.         words = string.split(bytes, '\0')
  118.         filename = words[0]
  119.         bytes = bytes[(len(words[0])+1):]
  120.         # skip \0
  121.         while bytes[0] == '\0':
  122.             bytes = bytes[1:]
  123.         subChunk.append(filename)
  124.     elif tag in ["TSIZ", "TCTR", "TFAL", "TVEL"]:
  125.         subChunk.append(tag)
  126.         values = struct.unpack(">3f", bytes[:12]) # big endian
  127.         bytes = bytes[12:]
  128.         subChunk.append(values)
  129.     elif tag == "TWRP":
  130.         subChunk.append(tag)
  131.         values = struct.unpack(">HH", bytes[:4])
  132.         bytes = bytes[4:]
  133.         subChunk.append(values)
  134.     else:
  135.         print tag
  136.         bytes = bytes[length:]
  137.     return subChunk, bytes
  138.  
  139. def readSurfaceList(file, length):
  140.     bytes = file.read(length)
  141.     words = string.split(bytes, '\0')
  142.     surfaceList = []
  143.     for word in words:
  144.         if word:
  145.             surfaceList.append(word)
  146.     return surfaceList
  147.  
  148. def isOnePolygon(indices):
  149.     for i in xrange(len(indices) - 1):
  150.         if indices[i] in (indices[0:i] + indices[(i+1):]):
  151.             return 0
  152.     return 1
  153.  
  154. def haveCommonCoords(pointList, indices, index):
  155.     testValue = pointList[0][index]
  156.     for i in indices:
  157.         if (pointList[i][index] - testValue) > 0.001:
  158.             return 0
  159.     return 1
  160.  
  161. def convertToInnerLoops(indices):
  162.     equal = []
  163.     outer = []
  164.     inner = []
  165.     # remove inner loops
  166.     for i in xrange(len(indices)):
  167.         for j in xrange(i+1, len(indices)):
  168.             if i != j and indices[i] == indices[j]:
  169.                 equal.append([i, j])
  170.     if (len(equal) == 2 and equal[0][0] == (equal[1][0] - 1) and
  171.         equal[0][1] == (equal[1][1] + 1)):
  172.         outer = indices[:equal[0][0]] + indices[equal[0][1]:]
  173.         inner = indices[equal[1][0]:equal[1][1]]
  174. ##         print equal
  175. ##         print indices
  176. ##         print outer
  177. ##         print inner
  178.     return outer, inner
  179.  
  180. def testLwo2iv(filename):
  181.     print 'testLightwave("%s")' % filename
  182.     file = open(filename, "rb")
  183.     tag, length = readChunk(file)
  184.     if tag == "FORM":
  185.         lwob = file.read(4)
  186.         if lwob == "LWOB":
  187.             filelength = length
  188.             numBytes = 4
  189.             while (numBytes < filelength):
  190.                 tag, length = readChunk(file)
  191.                 numBytes = numBytes + 8
  192.                 if length % 2 != 0:
  193.                     print "usage of pad byte"
  194.                     length = length + 1
  195.                 # surface list
  196.                 if tag == "SRFS":
  197.                     surfaceList = readSurfaceList(file, length)
  198.                 # point list
  199.                 elif tag == "PNTS":
  200.                     pointList = readPointList(file, length)
  201.                 # face list
  202.                 elif tag == "POLS":
  203.                     faceList = readFaceList(file, length)
  204.                 # surface definition
  205.                 elif tag == "SURF":
  206.                     surfaceDefinition = readSurfaceDefinition(file, length)
  207.                 else:
  208.                     file.read(length)
  209.                 numBytes = numBytes + length
  210.         else:
  211.             print 'No "LightWave 3D Object File Format" found :-['
  212.     file.close()
  213.     #########################
  214.     # write to OpenInventor #
  215.     #########################
  216.     file = open("test.iv", "w")
  217.     print "exporting ..."
  218.     # header
  219.     file.write("#Inventor V2.1 ascii\n\n")
  220.     file.write("Separator {\n")
  221.     file.write("  ShapeHints {\n")
  222.     file.write("    vertexOrdering COUNTERCLOCKWISE\n")
  223.     file.write("  }\n")
  224.     # vertices
  225.     file.write("  Coordinate3 {\n")
  226.     file.write("    point [\n")
  227.     for vertex in pointList[:-1]:
  228.         file.write("            %s %s %s,\n" %
  229.                         (vertex[0], vertex[1], vertex[2]))
  230.     vertex = pointList[-1]
  231.     file.write("            %s %s %s\n" %
  232.                     (vertex[0], vertex[1], vertex[2]))
  233.     file.write("          ]\n")
  234.     file.write("  }\n")
  235.     # faces
  236.     for materialIndex in xrange(1, len(surfaceList) + 1):
  237.         file.write("  Separator {\n")
  238.         file.write("    # %s\n" % surfaceList[materialIndex-1])
  239.         file.write("    Material {\n")
  240.         file.write("      diffuseColor 1 1 1\n")
  241.         file.write("    }\n")
  242.         file.write("    IndexedFaceSet {\n")
  243.         file.write("      coordIndex [\n")
  244.         for face in faceList:
  245.             numvert, vert, surf = face
  246.             if surf == materialIndex:
  247.                 if numvert == 3:
  248.                     file.write("                   %s, %s, %s, -1,\n" %
  249.                                (vert[0], vert[1], vert[2]))
  250.                 elif numvert == 4:
  251.                     file.write("                   %s, %s, %s, %s, -1,\n" %
  252.                                (vert[0], vert[1], vert[2], vert[3]))
  253. ##                 else:
  254. ##                     print face
  255.         file.write("                 ]\n")
  256.         file.write("    }\n")
  257.         # all non-triangles and non-quads
  258.         # -------------------------------
  259.         # try to export some of them
  260.         file.write("    # %s\n" % surfaceList[materialIndex-1])
  261.         file.write("    Material {\n")
  262.         file.write("      diffuseColor 0 1 0\n")
  263.         file.write("    }\n")
  264.         file.write("    IndexedFaceSet {\n")
  265.         file.write("      coordIndex [\n")
  266.         for face in faceList:
  267.             numvert, vert, surf = face
  268.             if surf == materialIndex:
  269.                 # one polygon
  270.                 if numvert != 3 and numvert != 4 and isOnePolygon(vert):
  271.                     testIndex = -1
  272.                     if haveCommonCoords(pointList, vert, 0):
  273.                         testIndex = 0
  274.                         tmpFile = open("data", "w")
  275.                         tmpFile.write("1\n\n%s\n" % len(vert))
  276.                         for i in vert:
  277.                             tmpFile.write("%s %s\n" % (pointList[i][1],
  278.                                                        pointList[i][2]))
  279.                         tmpFile.close()
  280.                     if haveCommonCoords(pointList, vert, 1):
  281.                         testIndex = 1
  282.                         tmpFile = open("data", "w")
  283.                         tmpFile.write("1\n\n%s\n" % len(vert))
  284.                         for i in vert:
  285.                             tmpFile.write("%s %s\n" % (pointList[i][0],
  286.                                                        pointList[i][2]))
  287.                         tmpFile.close()
  288.                     if haveCommonCoords(pointList, vert, 2):
  289.                         testIndex = 2
  290.                         tmpFile = open("data", "w")
  291.                         tmpFile.write("1\n\n%s\n" % len(vert))
  292.                         for i in vert:
  293.                             tmpFile.write("%s %s\n" % (pointList[i][0],
  294.                                                        pointList[i][1]))
  295.                         tmpFile.close()
  296.                     if testIndex != -1:
  297.                         tmpFile = os.popen("./triangulate data\n")
  298.                         info = tmpFile.readlines()
  299.                         tmpFile.close()
  300.                         for line in info:
  301.                             words = string.split(line)
  302.                             v1 = int(words[2]) - 1
  303.                             v2 = int(words[3]) - 1
  304.                             v3 = int(words[4]) - 1
  305.                             file.write("                   %s, %s, %s, -1,\n" %
  306.                                        (vert[v1], vert[v2], vert[v3]))
  307.                 # polygon with subloops
  308. ##                 if numvert != 3 and numvert != 4 and not isOnePolygon(vert):
  309. ##                     outer, inner = convertToInnerLoops(vert)
  310. ##                     testIndex = -1
  311. ##                     if haveCommonCoords(pointList, outer, 0):
  312. ##                         testIndex = 0
  313. ##                         tmpFile = open("data", "w")
  314. ##                         tmpFile.write("2\n\n%s\n" % len(outer))
  315. ##                         for i in outer:
  316. ##                             tmpFile.write("%s %s\n" % (pointList[i][1],
  317. ##                                                        pointList[i][2]))
  318. ##                         tmpFile.write("\n%s\n" % len(inner))
  319. ##                         for i in inner:
  320. ##                             tmpFile.write("%s %s\n" % (pointList[i][1],
  321. ##                                                        pointList[i][2]))
  322. ##                         tmpFile.close()
  323. ##                     if haveCommonCoords(pointList, outer, 1):
  324. ##                         testIndex = 1
  325. ##                         tmpFile = open("data", "w")
  326. ##                         tmpFile.write("2\n\n%s\n" % len(outer))
  327. ##                         for i in outer:
  328. ##                             tmpFile.write("%s %s\n" % (pointList[i][0],
  329. ##                                                        pointList[i][2]))
  330. ##                         tmpFile.write("\n%s\n" % len(inner))
  331. ##                         for i in inner:
  332. ##                             tmpFile.write("%s %s\n" % (pointList[i][0],
  333. ##                                                        pointList[i][2]))
  334. ##                         tmpFile.close()
  335. ##                     if haveCommonCoords(pointList, outer, 2):
  336. ##                         testIndex = 2
  337. ##                         tmpFile = open("data", "w")
  338. ##                         tmpFile.write("2\n\n%s\n" % len(outer))
  339. ##                         for i in outer:
  340. ##                             tmpFile.write("%s %s\n" % (pointList[i][0],
  341. ##                                                        pointList[i][1]))
  342. ##                         tmpFile.write("\n%s\n" % len(inner))
  343. ##                         for i in inner:
  344. ##                             tmpFile.write("%s %s\n" % (pointList[i][0],
  345. ##                                                        pointList[i][1]))
  346. ##                         tmpFile.close()
  347. ##                     if testIndex != -1:
  348. ##                         tmpFile = os.popen("./triangulate data\n")
  349. ##                         info = tmpFile.readlines()
  350. ##                         tmpFile.close()
  351. ##                         for line in info:
  352. ##                             words = string.split(line)
  353. ##                             v1 = int(words[2]) - 1
  354. ##                             v2 = int(words[3]) - 1
  355. ##                             v3 = int(words[4]) - 1
  356. ##                             file.write("                   %s, %s, %s, -1,\n" %
  357. ##                                        (vert[v1], vert[v2], vert[v3]))
  358.         file.write("                 ]\n")
  359.         file.write("    }\n")
  360.         # the rest of non-triangles and non-quads
  361.         file.write("    Material {\n")
  362.         file.write("      diffuseColor 1 0 0\n")
  363.         file.write("    }\n")
  364.         file.write("    IndexedLineSet {\n")
  365.         file.write("      coordIndex [\n")
  366.         for face in faceList:
  367.             numvert, vert, surf = face
  368.             if surf == materialIndex:
  369.                 if numvert != 3 and numvert != 4:
  370.                     file.write("                   ")
  371.                     for i in xrange(numvert):
  372.                         file.write("%s, " % vert[i])
  373.                     file.write("-1,\n")
  374.         file.write("                 ]\n")
  375.         file.write("    }\n")
  376.         file.write("  }\n")
  377.     # finish
  378.     file.write("}\n")
  379.     print "... finished"
  380.     file.close()
  381.  
  382. if __name__ == "__main__":
  383.     if len(sys.argv) != 2:
  384.         usage()
  385.     else:
  386.         filename = sys.argv[1]
  387.         testLwo2iv(filename)
  388.